﻿using IdentityServer4.Configuration;
using IdentityServer4.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Naruto.Id4.MongoDB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Authorization.Infrastructure.Extensions
{
    /// <summary>
    /// id4的扩展
    /// </summary>
    public static class Id4Extension
    {
        /// <summary>
        /// 添加一个identityserver4 
        /// </summary>
        /// <param name="services"></param>
        /// <param name="authorityUrl">授权的地址</param>
        /// <returns></returns>
        public static IServiceCollection AddIds4<TUser>(this IServiceCollection services, Action<IdentityServerMongoContext> context, string authorityUrl) where TUser : IdentityUser
        {
            //注入
            services.AddIdentityServer(options =>
            {
                //开启事件
                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                //配置用户交互页面定向设置处理
                options.UserInteraction = new UserInteractionOptions()
                {
                    ConsentUrl = "/consent",
                    ErrorUrl = "/error"
                };
                options.IssuerUri = authorityUrl;
                // 当使用 nginx 作为https的反向代理的时候，此参数不填写会导致访问的授权地址不是https的,直接会出现404错误
                //，解决方案是 将授权地址的https地址 填写到此参数中
                //,当使用http的时候，没有此问题
                options.PublicOrigin = authorityUrl;
            }).
            //注入证书
            AddDeveloperSigningCredential()
            //将默认的textuser替换成identityuser
            .AddAspNetIdentity<TUser>()
            //.AddProfileService<T>()
            //使用mongodb存储
            .AddMongoDBConfigurationStore(context)
            .AddMongoDBOperationalStore(options =>
            {
                //开启清理token的服务
                options.EnableTokenCleanup = true;
                //每次清理的过期的token的条数
                options.TokenCleanupBatchSize = 100;
                // 服务隔多久执行
                options.TokenCleanupInterval = 1200;
            });
            return services;
        }

        /// <summary>
        /// 注入.net identity
        /// </summary>
        /// <param name="services"></param>
        /// <param name="cookieName">cookie的名称</param>
        /// <returns></returns>
        public static IServiceCollection AddAspNetIdentity<TUser, TDbContext>(this IServiceCollection services, string cookieName) where TDbContext : DbContext where TUser : IdentityUser
        {
            #region .net identity

            services.Configure<DataProtectionTokenProviderOptions>(options =>
            {
                options.Name = "Default";
                options.TokenLifespan = TimeSpan.FromMinutes(15);
            });
            services.AddIdentity<TUser, IdentityRole>()
                .AddEntityFrameworkStores<TDbContext>()
                .AddSignInManager()
                .AddDefaultTokenProviders();
            services.Configure<IdentityOptions>(options =>
            {
                // Password settings.
                options.Password.RequireDigit = true;//获取或设置一个标志，指示密码是否必须包含数字。默认为true。
                options.Password.RequireLowercase = false;//获取或设置一个标志，指示密码是否必须包含小写ASCII字符。默认为true。
                options.Password.RequireNonAlphanumeric = false;//获取或设置一个标志，指示密码是否必须包含非字母数字字符。默认为true。
                options.Password.RequireUppercase = false;//获取或设置一个标志，指示密码是否必须包含大写ASCII字符。默认为true。
                options.Password.RequiredLength = 6;//获取或设置密码必须的最小长度。默认为6。
                options.Password.RequiredUniqueChars = 1;//获取或设置密码必须包含的最小唯一字符数。默认为1。
                // Lockout settings.
                options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
                options.Lockout.MaxFailedAccessAttempts = 5;
                options.Lockout.AllowedForNewUsers = true;

                // User settings.
                options.User.AllowedUserNameCharacters =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
                options.User.RequireUniqueEmail = false;

            });

            //配置应用程序的cookie 的参数设置 
            services.ConfigureApplicationCookie(option =>
            {
                //cookie的名称
                option.Cookie.Name = cookieName;
                option.ExpireTimeSpan = TimeSpan.FromDays(1);// 3.0版本的过期时间
                option.Cookie.HttpOnly = true;
                option.LoginPath = new PathString("/oauth2/authorize");//登录地址
                option.AccessDeniedPath = new PathString("/accessdenied");//无权限访问的路径
                option.LogoutPath = new PathString("/loginout");//退出登录地址
            });
            #endregion

            return services;
        }
        /// <summary>
        /// 注册中间件
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>

        public static IApplicationBuilder UseIds4(this IApplicationBuilder app)
        {
            app.UseIdentityServer();
            return app;
        }
    }
}
